﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using AzukiMap.Layer;
using GeoAPI.Geometries;
using Point=GisSharpBlog.NetTopologySuite.Geometries.Point;
using AzukiMap.Tools.Logger;

namespace AzukiMap.Renderer
{
    public class SimpleRenderer : RasterRendererCore
    {
        public SimpleRenderer(MapLayer layer)
            : base(layer)
        {
        }

        public override IList<FrameworkElement> CreateImages(Uri imageUri, IPolygon imagePoly)
        {
            var elements = new List<FrameworkElement>();

            double imageGeoWidth = GetGeoWidth(imagePoly);
            double imageGeoHeight = GetGeoHeight(imagePoly);

            var img = new Image();
            // TODO: this makes a memory leak problem.
            //img.ImageFailed += source_ImageFailed;

            ImageSource imgsrc = new BitmapImage(imageUri);
            img.Source = imgsrc;
            img.Width = GetImageWidth(imageGeoWidth) + TileAdjustPixel;
            img.Height = GetImageHeight(imageGeoHeight) + TileAdjustPixel;
            img.Stretch = Stretch.Fill;

            SetImageTransform(img, imageGeoWidth, imageGeoHeight);
            SetImageOrigin(img, imagePoly);

            elements.Add(img);

            return elements;
        }

        public override bool IsFitToDraw(IPolygon imagePolyOnMap, ImageMidPoints imageMidpointsOnMap)
        {
            double geoWidth = imagePolyOnMap.EnvelopeInternal.Width;
            double geoHeight = imagePolyOnMap.EnvelopeInternal.Height;
            double imageWidth = GetImageWidth(geoWidth);
            double imageHeight = GetImageHeight(geoHeight);
            double perPixX = geoWidth/imageWidth;
            double perPixY = geoHeight/imageHeight;

            //ICoordinate origin = new Coordinate(imagePolyOnMap.EnvelopeInternal.MinX, imagePolyOnMap.EnvelopeInternal.MaxY);
            IPoint origin = new Point(imagePolyOnMap.EnvelopeInternal.MinX, imagePolyOnMap.EnvelopeInternal.MaxY);

            // Check if the center left point is in the acceptable point.
            System.Windows.Point imageCL = GetPointOnImage(imageMidpointsOnMap.onMapCL, origin, perPixX, perPixY);
            var correctCL = new System.Windows.Point(0, imageHeight/2);
            if (!IsAccuratedPoint(imageCL, correctCL))
                return false;

            System.Windows.Point imageCR = GetPointOnImage(imageMidpointsOnMap.onMapCR, origin, perPixX, perPixY);
            var correctCR = new System.Windows.Point(imageWidth, imageHeight/2);
            if (!IsAccuratedPoint(imageCR, correctCR))
                return false;

            System.Windows.Point imageTC = GetPointOnImage(imageMidpointsOnMap.onMapTC, origin, perPixX, perPixY);
            var correctTC = new System.Windows.Point(imageWidth/2, 0);
            if (!IsAccuratedPoint(imageTC, correctTC))
                return false;

            System.Windows.Point imageBC = GetPointOnImage(imageMidpointsOnMap.onMapBC, origin, perPixX, perPixY);
            var correctBC = new System.Windows.Point(imageWidth/2, imageHeight);
            if (!IsAccuratedPoint(imageBC, correctBC))
                return false;

            System.Windows.Point imageCC = GetPointOnImage(imageMidpointsOnMap.onMapCC, origin, perPixX, perPixY);
            var correctCC = new System.Windows.Point(imageWidth/2, imageHeight/2);
            if (!IsAccuratedPoint(imageCC, correctCC))
                return false;

            return true;
        }

        private void SetImageTransform(Image img, double imageGeoWidth, double imageGeoHeight)
        {
            var transGroup = new TransformGroup();
            var moveTransform = new TranslateTransform();
            var scaleTransform = new ScaleTransform();

            double geoAspectRatio = imageGeoWidth/imageGeoHeight;
            double imgAspectRatio = img.Width/img.Height;
            double scaleX = geoAspectRatio/imgAspectRatio;

            double moveX = GetImageWidth(imageGeoWidth)*((scaleX - 1)/2)*-1;

            scaleTransform.ScaleX = scaleX;
            moveTransform.X = moveX;

            transGroup.Children.Add(scaleTransform);
            transGroup.Children.Add(moveTransform);

            img.RenderTransform = transGroup;
        }

    }
}